///////////////////////////////////////////////////////////////////////////
// Copyright 2009 Arabic Game Developer Network All rights reserved
// www.agd-online.com - info@agdn-online.com
// Parts of this code are based on code originally authored by Salwan Alhilali
// for the kvalley2 project. 
// Copyright 2008, In|Framez Co., All rights reserved
// 
// File: game.cpp
// Description: Valley's main system file. Contains high-level
//				application and global functionalities...
//
///////////////////////////////////////////////////////////////////////////

// This file is part of kvalleyX.
// 
// kvalleyX is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// kvalleyX is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with kvalleyX.  If not, see <http://www.gnu.org/licenses/>.


/////////////////// #includes /////////////////////////////////////////////
#include "game.h"
#include <string.h> ///TODO: for memset. check if same on Windows.
//#include <io.h>


/////////////////// Functions Implementations /////////////////////////////

///////////////////////////////////////////////////////////////////////////
// Function Name : GetGameFilePath
//
// Purpose : Maps a file resource path to the full physical path, and tests for its presence.
//
// Params : 
//    char *pszOutPath : (Out) Buffer to receive full file path.
//    const char *pszFileName : Name of requested file.
//    GameDirectories dirBase : File type (this determines its directory).
//
// Return Value : 'true' if file exists. 'false' if not.
////////////////////////////////////////////////////////////////////////////
bool GetGameFilePath(char *pszOutPath,const char *pszFileName,GameDirectories dirBase)
{
	/*static const char* aDirectories[] =
	{
		".",		// GameDir_Config
		"Art",		// GameDir_SpriteArt
		"Art",		// GameDir_BackgroundArt
		"Art",		// GameDir_BlockArt,
		"Art",		// GameDir_Font
		"Levels",	// GameDir_Level
		"Audio",	// GameDir_Audio
	};

	char szModulePath[MAX_PATH] = "";
	GetModuleFileName(NULL,szModulePath,sizeof(szModulePath));
	char szDrive[MAX_PATH], szDir[MAX_PATH];
	_splitpath(szModulePath,szDrive,szDir,NULL,NULL);

	if (dirBase == GameDir_Level)
		sprintf(pszOutPath,"%s%sData\\%s\\%s.lvl",szDrive,szDir,aDirectories[dirBase],pszFileName); // Special case
	else sprintf(pszOutPath,"%s%sData\\%s\\%s",szDrive,szDir,aDirectories[dirBase],pszFileName);

	// Ensure it's there
	_finddata_t fDisc;
	intptr_t fDiscHandle = _findfirst(pszOutPath,&fDisc);
	if (fDiscHandle != -1)
		_findclose(fDiscHandle);

	return (fDiscHandle == -1) ? false : true;
	*/
	sprintf(pszOutPath, "%s", pszFileName);
	return true;
}


/////////////////// Game Class Implementation ///////////////////////////
CONFIG Game::Config;

Game::Game() :
	m_bDrawGrid(false)
{
	memset(&Stats,0,sizeof(Stats));
	Stats.iCurrentLevel = 0;
	Stats.iLevelCleared = -1;
	Stats.iScore = 0;
	Stats.iHighScore = 0;
	Stats.iAttempts = 0;
	m_szStatsText[0] = 0;
}

Game& Game::getInstance()
{
	static Game instance;
	return instance;
}

Game::~Game()
{
	/*if (Pyramid::Current())
		delete Pyramid::Current();

	SpriteArt::ClearLibrary();
	CoreLib::BackgroundArt::ClearLibrary();
	BlockArt::ClearLibrary();
	AudioShutdown();

	Instance = NULL;

	// --NewCode: Salwan
	inputManager.RemoveAllControls();
	// --End
	*/
}

bool Game::init(void)
{
	///TODO: init/load game/ current stage resources here
// 	if (!AudioInit())
// 		return false;

	///TODO: check this out again
	if (!GameFont.Load("KonamiFont"))
		return false;
//	if (!LoadConfig()) return false;

	stateFlow.initStates();
	stateFlow.start();

	return true;
}

// void Game::UpdateStatsText(void)
// {
// 	//sprintf(m_szStatsText,"@IN|FRAMEZ   PYRAMID-%02d   
// 	//*KONAMI",Stats.iCurrentLevel);
// }

////////////////////////////////////////////////////////////////////////////
// Function Name : Game::DrawStats
//
// Purpose : Draws score and level information on the screen.
//
// Params : 
//    bool bCopyrights : 'true' to draw copyright info too. 'false' to hide it.
//
// Return Value : None.
////////////////////////////////////////////////////////////////////////////
// void Game::DrawStats(bool bCopyrights)
// {
// 	/*char szText[64];
// 	sprintf(szText,"SCORE-%06d HI-%06d
// ATTEMPT-%02d",Stats.iScore,Stats.iHighScore,Stats.iAttempts);
// 	GameFont.Draw(CHAMBER_LEFT+CHAMBER_CELL*2,CHAMBER_TOP-2,szText);
// 
// 	if (bCopyrights)
// 
// GameFont.Draw(CHAMBER_LEFT+CHAMBER_CELL*2,CHAMBER_BOTTOM+CHAMBER_CELL+8,
// m_szStatsText);
// 	*/
// }

void Game::SwitchFullscreen(void)
{
	CoreLib::LibSwitchFullScreen();
	m_bFullScreen = !m_bFullScreen;
}

////////////////////////////////////////////////////////////////////////////
// Function Name : Game::OnIdle
//
// Purpose : Callback function invoked whenever it is time to tick the 
// game's simulation.
//
// Params : None.
//
// Return Value : 
////////////////////////////////////////////////////////////////////////////
bool Game::update(void)
{
// --NewCode: Salwan
// 	inputManager.Update();
	// --End
	stateFlow.update(); /// update the state machine
// 	AudioUpdate();
	return true;
}

////////////////////////////////////////////////////////////////////////////
// Function Name : Game::OnDraw
//
// Purpose : Callback function invoked whenever it is time to draw the next
// game frame.
//
// Params : None.
//
// Return Value : 'true' if everything went well. 'false' if errors were 
// faced.
////////////////////////////////////////////////////////////////////////////
// bool Game::OnDraw(uint32_t ellapsedTime)
// {
// 	stateFlow.render();/// TODO: check if we need ellapsedTime as parameter.
// 	return true;
// }

bool Game::LoadConfig(void)
{
	/*char szFileName[MAX_PATH];
	if (!GetGameFilePath(szFileName,"MainConfig.cfg",GameDir_Config))
		return false;

	CoreLib::ConfigDB db;
	if (!CoreLib::XFerConfig(szFileName,db))
		return false;

	Config.pExplorerWalkArt = SpriteArt::GetOrLoadSpriteArt(db.szArtFile[0]);
	Config.pExplorerAxeArt = SpriteArt::GetOrLoadSpriteArt(db.szArtFile[1]);
	Config.pExplorerSwordArt = SpriteArt::GetOrLoadSpriteArt(db.szArtFile[2]);
	Config.pExplorerDigArt = SpriteArt::GetOrLoadSpriteArt(db.szArtFile[3]);
	Config.pExplorerShootArt = SpriteArt::GetOrLoadSpriteArt(db.szArtFile[4]);
	Config.pExplorerTorchArt = SpriteArt::GetOrLoadSpriteArt(db.szArtFile[5]);
	Config.pExplorerTorchStandArt =
SpriteArt::GetOrLoadSpriteArt(db.szArtFile[6]);

	if (!Config.pExplorerWalkArt || !Config.pExplorerAxeArt ||
!Config.pExplorerSwordArt ||
		!Config.pExplorerDigArt || !Config.pExplorerShootArt ||
!Config.pExplorerTorchArt ||
		!Config.pExplorerTorchStandArt)
		return false;

	(GameData::Config&)Config = db.data;
	return true;
	*/
	return false;
}

////////////////////////////////////////////////////////////////////////////
// Function Name : Game::SetupGameControls
//
// Purpose : Assigns game controls to keys on the keyboard and buttons/axes
// on the joystick.
//
// Params : None.
//
// Return Value : None.
////////////////////////////////////////////////////////////////////////////
void Game::SetupGameControls(void)
{
	using namespace CoreLib;
	CoreLib::InputManager& inputManager =
				CoreLib::Core2::getInstance().getInputManager();
	inputManager.KeyboardAssignControl(GameControl_Enter,
										 InputManager::INPUTK_RETURN);
	inputManager.KeyboardAssignControl(GameControl_Select,
										 InputManager::INPUTK_SPACE);
	inputManager.KeyboardAssignControl(GameControl_Up,
										 InputManager::INPUTK_UP);
	inputManager.KeyboardAssignControl(GameControl_Up,
										 InputManager::INPUTK_KP8);
	inputManager.KeyboardAssignControl(GameControl_Down,
										 InputManager::INPUTK_DOWN);
	inputManager.KeyboardAssignControl(GameControl_Down,
										 InputManager::INPUTK_KP2);
	inputManager.KeyboardAssignControl(GameControl_Left,
										 InputManager::INPUTK_LEFT);
	inputManager.KeyboardAssignControl(GameControl_Left,
										 InputManager::INPUTK_KP4);
	inputManager.KeyboardAssignControl(GameControl_Right,
										 InputManager::INPUTK_RIGHT);
	inputManager.KeyboardAssignControl(GameControl_Right,
										 InputManager::INPUTK_KP6);
	inputManager.KeyboardAssignControl(GameControl_Jump,
										 InputManager::INPUTK_SPACE);
	inputManager.KeyboardAssignControl(GameControl_Use,
										 InputManager::INPUTK_LCTRL);
	inputManager.KeyboardAssignControl(GameControl_MainMenu,
										 InputManager::INPUTK_F3);
	inputManager.KeyboardAssignControl(GameControl_RestartLevel,
										 InputManager::INPUTK_F2);
	inputManager.KeyboardAssignControl(GameControl_BackSpace,
										 InputManager::INPUTK_BACKSPACE);
	inputManager.KeyboardAssignControl(GameControl_Escape,
										 InputManager::INPUTK_ESCAPE);
	inputManager.KeyboardAssignControl(GameControl_Pause,
										 InputManager::INPUTK_F1);
	// A four button joystick will do
	//		Button0: Jump/Select (like Spacebar)
	//		Button1: Enter (or Use like CTRL)
	//		Button2: Restart Level
	//		Button3: Main Menu
	///TODO: add joystick support to the InputManager backends.
	/*inputManager.JoystickUpAssignControl(GameControl_Up);
	inputManager.JoystickDownAssignControl(GameControl_Down);
	inputManager.JoystickLeftAssignControl(GameControl_Left);
	inputManager.JoystickRightAssignControl(GameControl_Right);
	inputManager.JoystickButtonAssignControl(GameControl_Jump, 0);
	inputManager.JoystickButtonAssignControl(GameControl_Select, 0);
	inputManager.JoystickButtonAssignControl(GameControl_Enter, 1);
	inputManager.JoystickButtonAssignControl(GameControl_Use, 1);
	inputManager.JoystickButtonAssignControl(GameControl_RestartLevel, 2);
	inputManager.JoystickButtonAssignControl(GameControl_MainMenu, 3);
	*/
}


////////////////// End of File : game.cpp /////////////////////////////////
